<template>
<div>
    <div style="display: flex;flex-direction:row;flex-wrap:wrap">
        <el-input clearable placeholder="请输入文件名称" v-model="page.name" size="small" style="margin: 5px;width:200px">
        </el-input>
        <el-date-picker v-model="page.time" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" size="small" style="width: 200px;margin: 5px;" value-format="yyyy-MM-dd HH:mm:ss">
        </el-date-picker>
        <input type="file" name="filename" id="open" style="display: none" @change="changeFile" />
        <div>
            <el-button type="primary" size="small" @click="handleUpload" style="margin: 5px;">上传</el-button>
            <el-button type="primary" size="small" @click="handleRefresh" style="margin: 5px;">搜索</el-button>
        </div>
       
        <div style="height: 32px;margin:5px;line-height:32px">
            <el-button type="primary" size="small" v-if="progressInformation.length>0" style="margin: 5PX;" @click="handleCancleUpload">取消上传</el-button>
            {{ progressInformation }}</div>
        
    </div>
    <el-table :data="data" style="width: 100%" stripe :height="500"  v-loading="loading">
        <el-table-column prop="name" label="名称" align="center">
        </el-table-column>
        <el-table-column prop="md5" label="MD5" v-if="!smallPaginition" align="center">
        </el-table-column>
        <el-table-column prop="uploadTime" label="上传时间" width="180" align="center">
        </el-table-column>
        <el-table-column prop="path" label="路径" v-if="!smallPaginition" align="center">
        </el-table-column>
        <el-table-column fixed="right" label="操作" width="100" align="center" v-if="!smallPaginition">
            <template slot-scope="scope">

                <el-button type="text" size="small" @click="handleDownLoad(scope.row)">下载</el-button>
                <el-button type="text" size="small" style="color:red" @click="handleDelete(scope.row)" >删除</el-button>
            </template>
        </el-table-column>

    </el-table>
    <el-pagination style="margin-top: 10px;" :current-page.sync="page.current" :page-sizes="[5, 10, 20, 50]" :page-size.sync="page.pageSize" :layout="layout"
    @size-change="refresh" @current-change="refresh" :total="total" :small="smallPaginition">
    </el-pagination>
</div>
</template>

<script>
import axios from "axios";
import {
    getPageList,
    fileDownload,
    fileDelete
} from "@/api/fileInfo"
import request from '@/utils/request'
import SparkMD5 from "spark-md5";
import {
    fileMerge,
    fileQuery
} from "@/api/fileInfo"
export default {
    name: "fileInfo",
    data() {
        return {
            loading:true,
            //用于计算进度条
            progress: 0,
            progressInformation:"",
            data: [],
            total: 0,
            source: null,
            page: {
                "current": 1,
                "pageSize": 10,
                "name": "",
                "time": []

            },
            layout: "total, sizes, prev, pager, next, jumper",
            smallPaginition: false,
            baseUrl: ""
        }
    },
    created() {
        this.refresh()
        this.baseUrl = request.defaults.baseURL
        this.source = axios.CancelToken.source();

    },
    mounted() {
        this.handleResize();
        window.addEventListener('resize', this.handleResize);

    },
    methods: {
        handleCancleUpload(){
            source.cancel();
            this.refresh()
            this.$message.warning("上传已取消，未上传成功的部分可以选择重新上传，我们支持断点续传")
        },
        handleUpload() {
            document.getElementById("open").click();
        },
        changeFile() {
            const fu = document.getElementById("open");
            if (fu == null) return;
            this.click(fu.files[0]);
        },
        handleRefresh() {
            this.page.current=1
            this.refresh()
        },
        handleDownLoad(row) {
            fileDownload(row.id).then(res => {
                
                    
                    const url = window.URL.createObjectURL(res);
                    const link = document.createElement('a');
                    link.href = url;
                    // 把获得的blob的对象链接赋值给新创建的这个 a 链接
                    link.setAttribute('download', row.name); // 设置下载文件名
                    document.body.appendChild(link);
                    // 使用js点击这个链接
                    link.click();
                
            })
        },
        handleDelete(row) {
            fileDelete(row.id).then(res => {
                if (res.code == 200) {
                    this.$message.success("已删除")
                    this.refresh()
                } else {
                    this.$message.error(res.message)
                }
            })
        },
        refresh() {
            this.loading=true
            getPageList(this.page).then(res => {
                if (res.code == 200) {
                    this.data = res.data.records
                    this.total = res.data.total
                    
                } else {
                    this.$message.error(res.message)
                }
            }).finally(()=>{
                this.loading=false
            })
        },
        handleResize() {
            if (document.body.clientWidth < 768) {
                this.smallPaginition = true
                this.layout = "prev, pager, next"

            } else {
                this.smallPaginition = false
                this.layout = "total, sizes, prev, pager, next, jumper"

            }
        },
        //获取文件分片
        async getSliceFile(file, pieceSizes = 10) {
            const piece = 1024 * 1024 * pieceSizes;
            // 文件总大小
            const totalSize = file.size;
            // 每次上传的开始字节
            let start = 0;
            // 每次上传的结尾字节
            let end = start + piece;
            const chunks = [];
            while (start < totalSize) {
                const current = Math.min(end, totalSize);
                // 根据长度截取每次需要上传的数据
                // File对象继承自Blob对象，因此包含slice方法
                const blob = file.slice(start, current);
                chunks.push({
                    file: blob,
                    md5: await this.computeMD5(blob)
                });
                start = current;
                end = start + piece;
            }
            return chunks;
        },
        //上传文件，先判断远端有没有，没有就分片上传
        async click(file) {
            //判断远端是否存在该文件
            this.progressInformation="正在计算文件MD5特征值。。。"
            var amd5 = await this.computeMD5(file)
            this.progressInformation="正在根据MD5特征值查询服务器是否存储该文件。。。"
            const res = await fileQuery({
                md5: amd5
            })
            if (res.code == "204") {
                //文件远端不存在，继续上传
                //判断文件大小，分片
                this.progressInformation="切分文件，准备上传"
                const chunks = await this.getSliceFile(file, 10);
                var progressArray = []
                var md5s = []
                chunks.forEach(ele => {
                    md5s.push(ele.md5)
                })
                this.progressInformation="开始上传"
                chunks.forEach(async (ele, index) => {
                    
                    var formData = new FormData();

                    formData.append('file', ele.file);
                    formData.append("md5", ele.md5)
                    var that = this;
                    var res = await axios.post(this.baseUrl + "/file/upload", formData, {
                        headers: {
                            'Content-Type': 'multipart/form-data'
                        },
                        cancelToken: that.source.token,
                        onUploadProgress: function (e) {
                            const progress = Math.floor(
                                (e.loaded / e.total) * 100,
                            );
                            progressArray[index] = progress;
                            var temp = 0
                            progressArray.forEach(ele => {
                                temp += ele
                            })
                            that.progress = temp / chunks.length
                            that.progressInformation="上传进度"+that.progress
                            if (that.progress == 100) {
                                //全部上传，请求后端合并
                                that.progressInformation="上传完毕，服务器正在合并文件，请稍后"
                                fileMerge({
                                    name: file.name,
                                    md5s: md5s
                                }).then(res1 => {
                                    if (res1.code == 200) {
                                        that.progress = 0
                                        that.$message.success("上传成功")
                                        that.refresh()
                                        that.progressInformation=""
                                    } else {
                                        that.progressInformation="部分文件上传失败，准备上传这些文件"
                                        that.progress = 0
                                        that.click(file)
                                    }
                                })
                            }
                        }
                    })
                });
            } else {
                this.$message.success("已经上传，请勿重复上传")
                return false;
            }
        },
        //传入文件，计算MD5
        computeMD5(file) {
            return new Promise((resolve, reject) => {
                let fileReader = new FileReader();
                let Spark = new SparkMD5.ArrayBuffer();
                fileReader.readAsArrayBuffer(file);
                fileReader.onload = function (e) {
                    Spark.append(e.target.result);
                    let md5 = Spark.end();
                    resolve(md5);
                };
            })
        }
    }

}
</script>

<style></style>
